/*
 * Copyright (C) 2022 Texas Instruments Incorporated
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 *   Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the
 *   distribution.
 *
 *   Neither the name of Texas Instruments Incorporated nor the names of
 *   its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**************************************************************************
 *************************** Include Files ********************************
 **************************************************************************/

/* Standard Include Files. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <kernel/dpl/DebugP.h>
#include "FreeRTOS.h"
#include "task.h"

#include "mmw_cli.h"
#include <drivers/uart.h>
#include <drivers/prcm.h>
#include <drivers/pinmux.h>
#include <utils/mathutils/mathutils.h>
#include <common/syscommon.h>
#include "motion_detect.h"
#include <datapath/dpif/dpif_adcdata.h>
#include "mmw_res.h"
#include <datapath/dpu/cfarproc/v0/cfarprochwa.h>
#include <mmwavelink/include/rl_device.h>
#include "tracker_utils.h"

#include "ti_drivers_config.h"
#include "ti_drivers_open_close.h"
#include "ti_board_open_close.h"
#include "ti_board_config.h"

#define CLI_TASK_STACK_SIZE  (4 *1024U)
#define CLI_CFAR_THRESHOLD_ENCODING_FACTOR (100.0)

/* Demo Flash Address offset on 1MB */
#define MMWDEMO_CALIB_FLASH_ADDR_1MB  (uint32_t)(0x100000U)

//Enable this define, to allow dynamic swith to 1.25Mbps baud rate, then execute CLI cmd: baudRate 1250000
#define ENABLE_UART_HIGH_BAUD_RATE_DYNAMIC_CFG

#if defined (SOC_XWRL64XX)
#define DEVICE_STRING "xWRL6432"
#else
#define DEVICE_STRING "xWRL1432"
#endif

extern MmwDemo_MSS_MCB gMmwMssMCB;
extern uint8_t gATECalibDataStorage[];

TaskHandle_t gCliTask;
StaticTask_t gCliTaskObj;
StackType_t  gCliTskStack[CLI_TASK_STACK_SIZE] __attribute__((aligned(32)));

TaskHandle_t gDpcTask;
StaticTask_t gDpcTaskObj;
StackType_t  gDpcTaskStack[DPC_TASK_STACK_SIZE] __attribute__((aligned(32)));

TaskHandle_t gTlvTask;
StaticTask_t gTlvTaskObj;
StackType_t gTlvTaskStack[TLV_TASK_STACK_SIZE] __attribute__((aligned(32)));

TaskHandle_t gAdcFileTask;
StaticTask_t gAdcFileTaskObj;
StackType_t gAdcFileTaskStack[ADC_FILEREAD_TASK_STACK_SIZE] __attribute__((aligned(32)));

CLI_MCB     gCLI;
float       gSocClk = 40000000; //Hz TODO: Map from Syscfg generated config
// Indicate if Sensor is Started or not
uint8_t isSensorStarted = 0;
extern uint32_t sensorStop;

//#define CLI_BYPASS 1
#define MAX_RADAR_CMD 15
char* radarCmdString[MAX_RADAR_CMD] =
{
	"sensorStop 0 \n\r",
	"channelCfg 7 3 0 0 \n\r",
	"chirpComnCfg 23 0 0 128 4 0 1.5 937.5 36.1 1 \n\r",
	"chirpTimingCfg 8 24 0 47.95 60 3 3 \n\r",
	"frameCfg 2 0 169.8 64 250 0 \n\r",
	"guiMonitor 1 1 0 1 0 0 \n\r",
	"sigProcChainCfg 16 8 1 0 4 \n\r",
	"cfarCfg 2 8 2 3 0 6.02 1 0.5 0 1 1 1 \n\r",
	"aoaFovCfg -57 55 -57 56 \n\r",
	"rangeSelCfg 0.01 26.67 \n\r",
	"clutterRemoval 0 \n\r",
	"compRangeBiasAndRxChanPhase 0.0 1.00000 0.00000 -1.00000 0.00000 1.00000 0.00000 -1.00000 0.00000 1.00000 0.00000 -1.00000 0.00000 \n\r",
    "adcDataSource 0 C:\\\\ti\\\\Workarea\\\\Uploads\\\\mmwave_lp_sdk\\\\examples\\\\datapath\\\\common\\\\testBench\\\\major_motion\\\\adc_data_0001_CtestAdc6Ant.bin \n\r",
    "adcLogging 1 \n\r",
    "sensorStart 0 0 0 0 \n\r",
};

static Pinmux_PerCfg_t gPinMuxMDOCfg[] = {

            /* MDO0 pin config */
    /* MDO_CLK -> PAD_AW (L11) */
    {
        PIN_PAD_AW,
        ( PIN_MODE(7) | PIN_PULL_DISABLE )
    },
    /* MDO_FRMCLK -> PAD_AX (M10) */
    {
        PIN_PAD_AX,
        ( PIN_MODE(9) | PIN_PULL_DISABLE )
    },
    /* MDO_D0 -> PAD_AL (H10) */
    {
        PIN_PAD_AL,
        ( PIN_MODE(7) | PIN_PULL_DISABLE )
    },
    /* MDO_D1 -> PAD_AM (J11) */
    {
        PIN_PAD_AM,
        ( PIN_MODE(7) | PIN_PULL_DISABLE )
    },
    /* MDO_D2 -> PAD_AN (L12) */
    {
        PIN_PAD_AN,
        ( PIN_MODE(7) | PIN_PULL_DISABLE )
    },
    /* MDO_D3 -> PAD_AU (K11) */
    {
        PIN_PAD_AU,
        ( PIN_MODE(7) | PIN_PULL_DISABLE )
    },

    {PINMUX_END, PINMUX_END}
};

volatile unsigned long long demoStartTime = 0;
//cfar threshold in hwa = (cli_val * 100)/16

static int32_t CLI_help (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveExtensionHandler(int32_t argc, char* argv[]);
static void    CLI_MMWaveExtensionHelp(void);


static int32_t CLI_MMWaveVersion (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveSensorStop (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveChannelCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveChirpCommonCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveChirpTimingCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveFrameCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveGuiMonSel(int32_t argc, char* argv[]);
static int32_t CLI_MMWaveSigProcChainCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveCfarCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveAoaCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveRangeSelCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveClutterRemoval (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveCompRangeBiasAndRxChanPhaseCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveAdcDataSourceCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveAdcLogging (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveSensorPositionCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveMpdBoundaryBox (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveClusterParamCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveMajorMotionStateCfg (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveMinorMotionStateCfg (int32_t argc, char* argv[]);
int32_t CLI_MMWaveSensorStart (int32_t argc, char* argv[]);
static int32_t CLI_MMWaveFactoryCalConfig (int32_t argc, char* argv[]);
int32_t CLI_MMWStart(void);

/**************************************************************************
 ************************** Extern Definitions ****************************
 **************************************************************************/
extern void Mmwave_populateDefaultOpenCfg (MMWave_OpenCfg* ptrOpenCfg);
extern void Mmwave_populateDefaultChirpControlCfg (MMWave_CtrlCfg* ptrCtrlCfg);

extern int32_t MmwDemo_openSensor();
extern int32_t MmwDemo_configSensor(void);
extern int32_t MmwDemo_startSensor(void);
extern void mmwDemo_dpcTask();
extern void mmwDemo_TransmitProcessedOutputTask();
extern void mmwDemo_adcFileReadTask();

/**
 * @brief
 *  This is the mmWave extension table added to the CLI.
 */
CLI_CmdTableEntry gCLIMMWaveExtensionTable[] =
{
    {
        "version",
        "No arguments",
        CLI_MMWaveVersion
    },
    {
        NULL,
        NULL,
        NULL
    }
};

#ifdef CLI_BYPASS
static int32_t CLI_ByPassApi(CLI_Cfg* ptrCLICfg)
{
    //uint8_t                 cmdString[128];
    char*                   tokenizedArgs[CLI_MAX_ARGS];
    char*                   ptrCLICommand;
    char                    delimitter[] = " \r\n";
    uint32_t                argIndex;
    CLI_CmdTableEntry*      ptrCLICommandEntry;
    int32_t                 cliStatus;
    uint32_t                index, idx;
    uint16_t numCLICommands = 0U;

    /* Sanity Check: Validate the arguments */
    if (ptrCLICfg == NULL)
        return -1;

    /* Cycle through and determine the number of supported CLI commands: */
    for (index = 0; index < CLI_MAX_CMD; index++)
    {
        /* Do we have a valid entry? */
        if (ptrCLICfg->tableEntry[index].cmd == NULL)
        {
            /* NO: This is the last entry */
            break;
        }
        else
        {
            /* YES: Increment the number of CLI commands */
            numCLICommands = numCLICommands + 1;
        }
    }

    /* Execute All Radar Commands */
    for (idx = 0; idx < MAX_RADAR_CMD; idx++)
    {
        /* Reset all the tokenized arguments: */
        memset ((void *)&tokenizedArgs, 0, sizeof(tokenizedArgs));
        argIndex      = 0;
        ptrCLICommand = (char*)radarCmdString[idx];

        /* Set the CLI status: */
        cliStatus = -1;

        /* The command has been entered we now tokenize the command message */
        while (1)
        {
            /* Tokenize the arguments: */
            tokenizedArgs[argIndex] = strtok(ptrCLICommand, delimitter);
            if (tokenizedArgs[argIndex] == NULL)
                break;

            /* Increment the argument index: */
            argIndex++;
            if (argIndex >= CLI_MAX_ARGS)
                break;

            /* Reset the command string */
            ptrCLICommand = NULL;
        }

        /* Were we able to tokenize the CLI command? */
        if (argIndex == 0)
            continue;

        /* Cycle through all the registered CLI commands: */
        for (index = 0; index < numCLICommands; index++)
        {
            ptrCLICommandEntry = &ptrCLICfg->tableEntry[index];

            /* Do we have a match? */
            if (strcmp(ptrCLICommandEntry->cmd, tokenizedArgs[0]) == 0)
            {
                /* YES: Pass this to the CLI registered function */
                cliStatus = ptrCLICommandEntry->cmdHandlerFxn (argIndex, tokenizedArgs);
                if (cliStatus == 0)
                {
                    CLI_write ("Done\n\n");
                }
                else
                {
                    CLI_write ("Error %d\n", cliStatus);
                }
                break;
            }
        }

        /* Did we get a matching CLI command? */
        if (index == numCLICommands)
        {
            /* NO matching command found. Is the mmWave extension enabled? */
            if (ptrCLICfg->enableMMWaveExtension == 1U)
            {
                /* Yes: Pass this to the mmWave extension handler */
                cliStatus = CLI_MMWaveExtensionHandler (argIndex, tokenizedArgs);
            }

            /* Was the CLI command found? */
            if (cliStatus == -1)
            {
                /* No: The command was still not found */
                CLI_write ("'%s' is not recognized as a CLI command\r\n", tokenizedArgs[0]);
            }
        }
    }

    return 0;
}
#endif

/**
 *  @b Description
 *  @n
 *      This is the CLI Handler for the version command
 *
 *  @param[in] argc
 *      Number of arguments
 *  @param[in] argv
 *      Arguments
 *
 *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */
static int32_t CLI_MMWaveVersion (int32_t argc, char* argv[])
{
    int32_t       retVal = 0;
    T_RL_API_DFP_FW_VER_GET_RSP dfpVerapiResData;
    T_RL_API_SENSOR_DIEID_RSP   deviceDieId;

    if(gCLI.cfg.overridePlatform == false)
    {
#if defined (SOC_XWRL64XX)
        /* print the platform */
        CLI_write ("Platform                : XWRL6432\r\n");
#else
        /* print the platform */
        CLI_write ("Platform                : XWRL1432\r\n");
#endif
    }
    else
    {
        CLI_write ("Platform                : %s\r\n", gCLI.cfg.overridePlatformString);
    }

    /* Initialize API response Structures. */
    memset(&dfpVerapiResData,0,sizeof(T_RL_API_DFP_FW_VER_GET_RSP));
    memset(&deviceDieId,0,sizeof(T_RL_API_SENSOR_DIEID_RSP));

    /* Get the version string: */
    retVal = rl_mmWaveDfpVerGet(M_DFP_DEVICE_INDEX_0, &dfpVerapiResData);
    if (retVal < 0)
    {
        CLI_write ("Error: get DFP version [Error %d]\r\n", retVal);
        return -1;
    }

    CLI_write ("RFS Firmware Version    : %02d.%02d.%02d.%02d\r\n",
                dfpVerapiResData.z_RfsRomVersion.c_GenVerNum,
                dfpVerapiResData.z_RfsRomVersion.c_MajorVerNum,
                dfpVerapiResData.z_RfsRomVersion.c_MinorVerNum,
                dfpVerapiResData.z_RfsRomVersion.c_BuildVerNum);

    CLI_write ("FECSS Lib Version       : %02d.%02d.%02d.%02d\r\n",
                dfpVerapiResData.z_FecssLibVersion.c_GenVerNum,
                dfpVerapiResData.z_FecssLibVersion.c_MajorVerNum,
                dfpVerapiResData.z_FecssLibVersion.c_MinorVerNum,
                dfpVerapiResData.z_FecssLibVersion.c_BuildVerNum);

    CLI_write ("mmWaveLink Version      : %02d.%02d.%02d.%02d\r\n",
                dfpVerapiResData.z_MmwlLibVersion.c_GenVerNum,
                dfpVerapiResData.z_MmwlLibVersion.c_MajorVerNum,
                dfpVerapiResData.z_MmwlLibVersion.c_MinorVerNum,
                dfpVerapiResData.z_MmwlLibVersion.c_BuildVerNum);

    // /* Get Die ID. */
    // retVal = fe_fecssDieIdGet_rom(M_DFP_DEVICE_INDEX_0, &deviceDieId);
    // if (retVal < 0)
    // {
    //     CLI_write ("Error: get device die info [Error %d]\r\n", retVal);
    //     return -1;
    // }

    // CLI_write ("Die ID Val0 : 0x%X\r\n", deviceDieId.w_DieIdData[0]);
    // CLI_write ("Die ID Val1 : 0x%X\r\n", deviceDieId.w_DieIdData[1]);
    // CLI_write ("Die ID Val2 : 0x%X\r\n", deviceDieId.w_DieIdData[2]);
    // CLI_write ("Die ID Val3 : 0x%X\r\n", deviceDieId.w_DieIdData[3]);

    /* Display the version information on the CLI Console: */
    CLI_write ("mmWave SDK Version      : %02d.%02d.%02d.%02d\r\n",
                            MMWAVE_SDK_VERSION_MAJOR,
                            MMWAVE_SDK_VERSION_MINOR,
                            MMWAVE_SDK_VERSION_BUGFIX,
                            MMWAVE_SDK_VERSION_BUILD);
    /* Version string has been formatted successfully. */
    /* Display the Demo information on the CLI Console: */
    CLI_write ("Presence_Demo\r\n");
    return 0;
}

static int32_t CLI_MMWaveExtensionHandler(int32_t argc, char* argv[])
{
    CLI_CmdTableEntry*  ptrCLICommandEntry;
    int32_t             cliStatus;
    int32_t             retVal = 0;

    /* Get the pointer to the mmWave extension table */
    ptrCLICommandEntry = &gCLIMMWaveExtensionTable[0];

    /* Cycle through all the registered externsion CLI commands: */
    while (ptrCLICommandEntry->cmdHandlerFxn != NULL)
    {
        /* Do we have a match? */
        if (strcmp(ptrCLICommandEntry->cmd, argv[0]) == 0)
        {
            /* YES: Pass this to the CLI registered function */
            cliStatus = ptrCLICommandEntry->cmdHandlerFxn (argc, argv);
            if (cliStatus == 0)
            {
                /* Successfully executed the CLI command: */
                CLI_write ("Done\r\n\n");
            }
            else
            {
                /* Error: The CLI command failed to execute */
                CLI_write ("Error %d\r\n", cliStatus);
            }
            break;
        }

        /* Get the next entry: */
        ptrCLICommandEntry++;
    }

    /* Was this a valid CLI command? */
    if (ptrCLICommandEntry->cmdHandlerFxn == NULL)
    {
        /* NO: The command was not a valid CLI mmWave extension command. Setup
         * the return value correctly. */
        retVal = -1;
    }
    return retVal;
}

#define READ_LINE_BUFSIZE   256
/**
 *  @b Description
 *  @n
 *      This is the CLI Execution Task
 *
 *  \ingroup CLI_UTIL_INTERNAL_FUNCTION
 *
 *  @retval
 *      Not Applicable.
 */
static void CLI_task(void* args)
{
    #ifndef CLI_BYPASS
    uint8_t                 cmdString[READ_LINE_BUFSIZE];
    char*                   tokenizedArgs[CLI_MAX_ARGS];
    char*                   ptrCLICommand;
    char                    delimitter[] = " \r\n";
    uint32_t                argIndex;
    CLI_CmdTableEntry*      ptrCLICommandEntry;
    int32_t                 cliStatus, status;
    uint32_t                index;

    /* Do we have a banner to be displayed? */
    if (gCLI.cfg.cliBanner != NULL)
    {
        /* YES: Display the banner */
        CLI_write (gCLI.cfg.cliBanner);
    }

    /* Loop around forever: */
    while (1)
    {
        /* Demo Prompt: */
        CLI_write (gCLI.cfg.cliPrompt);

        /* Reset the command string: */
        memset ((void *)&cmdString[0], 0, sizeof(cmdString));

        status = CLI_readLine(gCLI.cfg.UartHandle, (char*)&cmdString[0], READ_LINE_BUFSIZE);
        if(status != SystemP_SUCCESS)
        {
            CLI_write("Error reading\n");
        }

        /* Reset all the tokenized arguments: */
        memset ((void *)&tokenizedArgs, 0, sizeof(tokenizedArgs));
        argIndex      = 0;
        ptrCLICommand = (char*)&cmdString[0];

        /* comment lines found - ignore the whole line*/
        if (cmdString[0]=='%' || cmdString[1]=='%')
        {
            CLI_write ("Skipped\n");
            continue;
        }

        /* Set the CLI status: */
        cliStatus = -1;

        /* The command has been entered we now tokenize the command message */
        while (1)
        {
            /* Tokenize the arguments: */
            tokenizedArgs[argIndex] = strtok(ptrCLICommand, delimitter);
            if (tokenizedArgs[argIndex] == NULL)
                break;

            /* Increment the argument index: */
            argIndex++;
            if (argIndex >= CLI_MAX_ARGS)
                break;

            /* Reset the command string */
            ptrCLICommand = NULL;
        }

        /* Were we able to tokenize the CLI command? */
        if (argIndex == 0)
            continue;

        /* Cycle through all the registered CLI commands: */
        for (index = 0; index < gCLI.numCLICommands; index++)
        {
            ptrCLICommandEntry = &gCLI.cfg.tableEntry[index];

            /* Do we have a match? */
            if (strcmp(ptrCLICommandEntry->cmd, tokenizedArgs[0]) == 0)
            {
                /* YES: Pass this to the CLI registered function */
                cliStatus = ptrCLICommandEntry->cmdHandlerFxn (argIndex, tokenizedArgs);
                if (cliStatus == 0)
                {
                    CLI_write ("Done\r\n\n");
                }
                else
                {
                    CLI_write ("Error %d\r\n", cliStatus);
                }
                break;
            }
        }

        /* Did we get a matching CLI command? */
        if (index == gCLI.numCLICommands)
        {
            /* NO matching command found. Is the mmWave extension enabled? */
            if (gCLI.cfg.enableMMWaveExtension == 1U)
            {
                /* Yes: Pass this to the mmWave extension handler */
                cliStatus = CLI_MMWaveExtensionHandler (argIndex, tokenizedArgs);
            }

            /* Was the CLI command found? */
            if (cliStatus == -1)
            {
                /* No: The command was still not found */
                CLI_write ("'%s' is not recognized as a CLI command\r\n", tokenizedArgs[0]);
            }
        }
    }
    #else

	CLI_ByPassApi(&gCLI.cfg);
    #endif
    /* Never return for this task. */
    SemaphoreP_pend(&gMmwMssMCB.cliInitTaskCompleteSemHandle, SystemP_WAIT_FOREVER);
}

static void CLI_MMWaveExtensionHelp(void)
{
    CLI_CmdTableEntry*  ptrCLICommandEntry;

    /* Get the pointer to the mmWave extension table */
    ptrCLICommandEntry = &gCLIMMWaveExtensionTable[0];

    /* Display the banner: */
    CLI_write ("****************************************************\n");
    CLI_write ("mmWave Extension Help\n");
    CLI_write ("****************************************************\n");

    /* Cycle through all the registered externsion CLI commands: */
    while (ptrCLICommandEntry->cmdHandlerFxn != NULL)
    {
        /* Display the help string*/
        CLI_write ("%s: %s\n",
                    ptrCLICommandEntry->cmd,
                   (ptrCLICommandEntry->helpString == NULL) ?
                    "No help available" :
                    ptrCLICommandEntry->helpString);

        /* Get the next entry: */
        ptrCLICommandEntry++;
    }
    return;
}

static int32_t CLI_help (int32_t argc, char* argv[])
{
    uint32_t    index;

    /* Display the banner: */
    CLI_write ("Help: This will display the usage of the CLI commands\n");
    CLI_write ("Command: Help Description\n");

    /* Cycle through all the registered CLI commands: */
    for (index = 0; index < gCLI.numCLICommands; index++)
    {
        /* Display the help string*/
        CLI_write ("%s: %s\n",
                    gCLI.cfg.tableEntry[index].cmd,
                   (gCLI.cfg.tableEntry[index].helpString == NULL) ?
                    "No help available" :
                    gCLI.cfg.tableEntry[index].helpString);
    }

    /* Is the mmWave Extension enabled? */
    if (gCLI.cfg.enableMMWaveExtension == 1U)
    {
        /* YES: Pass the control to the extension help handler. */
        CLI_MMWaveExtensionHelp ();
    }
    return 0;
}

static int32_t CLI_MMWaveLowPwrModeEnable(int32_t argc, char* argv[])
{
    if (argc != 2)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    gMmwMssMCB.lowPowerMode = atoi (argv[1]);
    return 0;
}

static int32_t CLI_MMWaveFrameCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 7)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate the frame configuration: */
    gMmwMssMCB.frameCfg.h_NumOfChirpsInBurst      = atoi (argv[1]);
    gMmwMssMCB.frameCfg.c_NumOfChirpsAccum        = atoi (argv[2]);
    gMmwMssMCB.burstPeriod                        = atof (argv[3]); //us
    gMmwMssMCB.frameCfg.h_NumOfBurstsInFrame      = atoi (argv[4]);
    gMmwMssMCB.frameCfg.w_FramePeriodicity        = ((atof (argv[5])) * gSocClk)/1000; // x crystal_clk_MHz x 1000
    gMmwMssMCB.frameCfg.h_NumOfFrames             = atoi (argv[6]);

    gMmwMssMCB.frameCfg.w_BurstPeriodicity = 10.0 * gMmwMssMCB.burstPeriod;

    return 0;
}

static int32_t CLI_MMWaveChirpTimingCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 6)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* TODO: Assumes Low res clock and to change */
    /* Populate the Chirp Timing configuration: */
    gMmwMssMCB.profileTimeCfg.h_ChirpIdleTime      = 10.0 * atof (argv[1]);
    gMmwMssMCB.profileTimeCfg.h_ChirpAdcStartTime  = (atoi (argv[2])) << 10; //num of skip samples
    gMmwMssMCB.profileTimeCfg.xh_ChirpTxStartTime  = 10.0 * (atof (argv[3]));
    gMmwMssMCB.chirpSlope                          = atof (argv[4]); //MHz/us
    gMmwMssMCB.startFreq                           = atof (argv[5]); //GHz

#ifdef SOC_XWRL64XX
    gMmwMssMCB.profileTimeCfg.xh_ChirpRfFreqSlope  = (gMmwMssMCB.chirpSlope * 1048576.0)/(3* 100 * 100);
    gMmwMssMCB.profileTimeCfg.w_ChirpRfFreqStart   = (gMmwMssMCB.startFreq * 1000.0 * 256.0)/(300);
#else
    gMmwMssMCB.profileTimeCfg.xh_ChirpRfFreqSlope  = (gMmwMssMCB.chirpSlope * 1048576.0)/(4* 100 * 100);
    gMmwMssMCB.profileTimeCfg.w_ChirpRfFreqStart   = (gMmwMssMCB.startFreq * 1000.0 * 256.0)/(400);
#endif

    return 0;
}

static int32_t CLI_MMWaveChirpCommonCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 8)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate the Chirp Common configuration: */
    gMmwMssMCB.profileComCfg.c_DigOutputSampRate  = atoi (argv[1]); //Range 8 to 100
    gMmwMssMCB.profileComCfg.c_DigOutputBitsSel   = atoi (argv[2]);
    gMmwMssMCB.profileComCfg.c_DfeFirSel          = atoi (argv[3]);
    gMmwMssMCB.profileComCfg.h_NumOfAdcSamples    = atoi (argv[4]);
    gMmwMssMCB.profileComCfg.c_ChirpTxMimoPatSel  = atoi (argv[5]);

    /* Chirp Common Config: MiscSettings and HPFFastInit Duration */
    gMmwMssMCB.profileComCfg.c_MiscSettings       = 0U;
    gMmwMssMCB.profileComCfg.c_HpfFastInitDuration= 15U; // 15uSec

    gMmwMssMCB.profileComCfg.h_ChirpRampEndTime   = 10.0 * atof (argv[6]);
    gMmwMssMCB.profileComCfg.c_ChirpRxHpfSel      = atoi (argv[7]);

    gMmwMssMCB.adcSamplingRate = 100.0/gMmwMssMCB.profileComCfg.c_DigOutputSampRate; //Range 1MHz to 12.5MHz
    gMmwMssMCB.numRangeBins = mathUtils_pow2roundup(gMmwMssMCB.profileComCfg.h_NumOfAdcSamples)/2; //Real only sampling

    if ((gMmwMssMCB.profileComCfg.c_ChirpTxMimoPatSel == 1) || (gMmwMssMCB.profileComCfg.c_ChirpTxMimoPatSel == 0))
    {
        /* TDM-MIMO*/
        gMmwMssMCB.isBpmEnabled = 0;
    }
    else if (gMmwMssMCB.profileComCfg.c_ChirpTxMimoPatSel == 4)
    {
        /* BPM-MIMO*/
        gMmwMssMCB.isBpmEnabled = 1;
    }
    else
    {
        CLI_write ("Error: c_ChirpTxMimoPatSel must have value either 1 (TDM-MIMO) or 4 (BPM-MIMO)\n");
        return -1;
    }

    return 0;
}

static int32_t CLI_MMWaveSigProcChainCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 9)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate configuration: */
    gMmwMssMCB.sigProcChainCfg.azimuthFftSize   = (uint16_t) atoi (argv[1]);
    gMmwMssMCB.sigProcChainCfg.elevationFftSize = (uint16_t) atoi (argv[2]);
    gMmwMssMCB.sigProcChainCfg.motDetMode       = (uint16_t) atoi (argv[3]);
    gMmwMssMCB.sigProcChainCfg.coherentDoppler  = (uint16_t) atoi (argv[4]);
    gMmwMssMCB.sigProcChainCfg.numFrmPerMinorMotProc = (uint16_t) atoi (argv[5]);
    gMmwMssMCB.sigProcChainCfg.numMinorMotionChirpsPerFrame    = (uint16_t) atoi (argv[6]);
    gMmwMssMCB.sigProcChainCfg.forceMinorMotionVelocityToZero    = (uint16_t) atoi (argv[7]);
    gMmwMssMCB.sigProcChainCfg.minorMotionVelocityInclusionThr    = (float) atof (argv[8]);

    if (gMmwMssMCB.sigProcChainCfg.motDetMode == 1)
    {
        gMmwMssMCB.enableMajorMotion = 1;
        gMmwMssMCB.enableMinorMotion = 0;
    }
    else if (gMmwMssMCB.sigProcChainCfg.motDetMode == 2)
    {
        gMmwMssMCB.enableMajorMotion = 0;
        gMmwMssMCB.enableMinorMotion = 1;
    }
    else if (gMmwMssMCB.sigProcChainCfg.motDetMode == 3)
    {
        gMmwMssMCB.enableMajorMotion = 1;
        gMmwMssMCB.enableMinorMotion = 1;
    }
    else
    {
        CLI_write ("Error: Motion Detection mode not valid\n");
        return -1;
    }

    return 0;
}

static int32_t CLI_MMWaveCfarCfg (int32_t argc, char* argv[])
{
    float               threshold;

    /* Sanity Check: Minimum argument check */
    if (argc != 13)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate configuration: */
    gMmwMssMCB.cfarCfg.averageMode       = (uint8_t) atoi (argv[1]);
    gMmwMssMCB.cfarCfg.winLen            = (uint8_t) atoi (argv[2]);
    gMmwMssMCB.cfarCfg.guardLen          = (uint8_t) atoi (argv[3]);
    gMmwMssMCB.cfarCfg.noiseDivShift     = (uint8_t) atoi (argv[4]);
    gMmwMssMCB.cfarCfg.cyclicMode        = (uint8_t) atoi (argv[5]);
    threshold                 = (float) atof (argv[6]);
    gMmwMssMCB.cfarCfg.peakGroupingEn    = (uint8_t) atoi (argv[7]);

    gMmwMssMCB.cfarCfg.sideLobeThresholdScaleQ8 = (int16_t) (atof (argv[8]) * DPU_CFARPROCHWA_ONE_Q8);
    gMmwMssMCB.cfarCfg.enableLocalMaxRange      = (uint8_t) atoi (argv[9]);
    gMmwMssMCB.cfarCfg.enableLocalMaxAzimuth    = (uint8_t) atoi (argv[10]);
    gMmwMssMCB.cfarCfg.enableInterpRangeDom     = (uint8_t) atoi (argv[11]);
    gMmwMssMCB.cfarCfg.enableInterpAzimuthDom   = (uint8_t) atoi (argv[12]);


    if (threshold > 100.0)
    {
        CLI_write("Error: Maximum value for CFAR thresholdScale is 100.0 dB.\n");
        return -1;
    }

    /* threshold is a float value from 0-100dB. It needs to
       be later converted to linear scale (conversion can only be done
       when the number of virtual antennas is known) before passing it
       to CFAR DPU.
       For now, the threshold will be coded in a 16bit integer in the following
       way:
       suppose threshold is a float represented as XYZ.ABC
       it will be saved as a 16bit integer XYZAB
       that is, 2 decimal cases are saved.*/
    //threshold = threshold * CLI_CFAR_THRESHOLD_ENCODING_FACTOR;
    threshold = pow(10, threshold/20.0) * 16.0 + 0.5;
    gMmwMssMCB.cfarCfg.thresholdScale    = (uint32_t) threshold;

    return 0;
}

static int32_t CLI_MMWaveAoaCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 5)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate configuration: */
    gMmwMssMCB.fovCfg.minAzimuthDeg      = (float) atoi (argv[1]);
    gMmwMssMCB.fovCfg.maxAzimuthDeg      = (float) atoi (argv[2]);
    gMmwMssMCB.fovCfg.minElevationDeg    = (float) atoi (argv[3]);
    gMmwMssMCB.fovCfg.maxElevationDeg    = (float) atoi (argv[4]);

    return 0;
}

static int32_t CLI_MMWaveCompRangeBiasAndRxChanPhaseCfg (int32_t argc, char* argv[])
{
    DPU_DoaProc_compRxChannelBiasCfg   cfg;
    int32_t Re, Im;
    int32_t argInd;
    int32_t i;

    /* Sanity Check: Minimum argument check */
    if (argc != (1+1+SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL*2))
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Initialize configuration: */
    memset ((void *)&cfg, 0, sizeof(cfg));

    /* Populate configuration: */
    cfg.rangeBias          = (float) atof (argv[1]);

    argInd = 2;
    for (i=0; i < SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL; i++)
    {
        Re = (int32_t) (atof (argv[argInd++]) * 1048576.);
        MATHUTILS_SATURATE21(Re);
        cfg.rxChPhaseComp[i].real = (int32_t) Re;

        Im = (int32_t) (atof (argv[argInd++]) * 1048576.);
        MATHUTILS_SATURATE21(Im);
        cfg.rxChPhaseComp[i].imag = (int32_t) Im;

    }
    /* Save Configuration to use later */
    memcpy((void *) &gMmwMssMCB.compRxChannelBiasCfg, &cfg, sizeof(cfg));

    // gMmwMssMCB.objDetCommonCfg.isCompRxChannelBiasCfgPending = 1; // ToDo

    return 0;
}

static int32_t CLI_MMWaveClutterRemoval (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 2)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate configuration: */
    gMmwMssMCB.staticClutterRemovalEnable          = (uint32_t) atoi (argv[1]);

    return 0;
}

static int32_t CLI_MMWaveAdcLogging (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 2)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate configuration: */
    gMmwMssMCB.adcLogging          = (uint32_t) atoi (argv[1]);

    if(gMmwMssMCB.adcLogging == true)
    {
        /* Configure MDIO pins for ADC data Transfer */
        Pinmux_config(gPinMuxMDOCfg, PINMUX_DOMAIN_ID_MAIN);

        /*  Enable MDLL Clock for RDIF interface */
        SOC_enableMDLLClock();
    }

    return 0;
}

static int32_t CLI_MMWaveRangeSelCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 3)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate configuration: */
    gMmwMssMCB.rangeSelCfg.min               = (float) atof (argv[1]);
    gMmwMssMCB.rangeSelCfg.max               = (float) atof (argv[2]);

    return 0;
}

static int32_t CLI_MMWaveSensorStop (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 2)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    if(isSensorStarted == 1)
    {
        sensorStop = 1;
    }

    return 0;
}

static int32_t CLI_MMWaveGuiMonSel (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 12)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate configuration: */
    gMmwMssMCB.guiMonSel.pointCloud      = atoi (argv[1]);
    gMmwMssMCB.guiMonSel.rangeProfile          = atoi (argv[2]);
    gMmwMssMCB.guiMonSel.noiseProfile         = atoi (argv[3]);
    gMmwMssMCB.guiMonSel.rangeAzimuthHeatMap  = atoi (argv[4]);
    gMmwMssMCB.guiMonSel.rangeDopplerHeatMap  = atoi (argv[5]);
    gMmwMssMCB.guiMonSel.statsInfo            = atoi (argv[6]);
    gMmwMssMCB.guiMonSel.presenceInfo          = atoi (argv[7]);
    gMmwMssMCB.guiMonSel.adcSamples            = atoi (argv[8]);
    gMmwMssMCB.guiMonSel.trackerInfo           = atoi (argv[9]);
    gMmwMssMCB.guiMonSel.microDopplerInfo      = atoi (argv[10]);
    gMmwMssMCB.guiMonSel.classifierInfo      = atoi (argv[11]);

    return 0;
}

/**
 *  @b Description
 *  @n
 *      This is the CLI Handler for ADC data source configuration
 *
 *  @param[in] argc
 *      Number of arguments
 *  @param[in] argv
 *      Arguments
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */
static int32_t CLI_MMWaveAdcDataSourceCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 3)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Save Configuration to use later */
    gMmwMssMCB.adcDataSourceCfg.source = atoi (argv[1]);
    strcpy(gMmwMssMCB.adcDataSourceCfg.fileName, argv[2]);

    return 0;
}



/**
 *  @b Description
 *  @n
 *      This is the CLI Handler for antenna geometry configuration
 *      Arguments are row/column coordinates of the virtual antennas in 
 *      units of lambda/2. The arguments are 
 *      <virtAnt0_row> <virtAnt0_col> <virtAnt1_row> <virtAnt1_col> ... <virtAnt5_row> <virtAnt5_col> <antennaDistanceXdim> <antennaDistanceZdim>
 *      where 
 *           virtAnt0 corresponds to tx0-rx0,
 *           virtAnt1 corresponds to tx0-rx1,
 *           virtAnt2 corresponds to tx0-rx2,
 *           virtAnt3 corresponds to tx1-rx0,
 *           virtAnt4 corresponds to tx1-rx1,
 *           virtAnt5 corresponds to tx1-rx2
 *      The last two parameters are optional and represent antenna spacing (mm)
 *         <antennaDistanceXdim> antenna spacing in X dimension
 *         <antennaDistanceZdim> antenna spacing in Z dimension
 *      If these two arguments are not specified, it is assumed that lambda/d=2 where d is distance beetween antennas.
 *  @param[in] argc
 *      Number of arguments
 *  @param[in] argv
 *      Arguments
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */
static int32_t CLI_MmwDemo_AntGeometryCfg (int32_t argc, char* argv[])
{
    MmwDemo_antennaGeometryCfg   cfg;
    int32_t argInd;
    int32_t i;

    /* Sanity Check: Minimum argument check */
    if ((argc < (1 + SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL*2)) ||
        (argc > (1 + SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL*2 + 2)))
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Initialize configuration: */
    memset ((void *)&cfg, 0, sizeof(cfg));


    argInd = 1;
    for (i=0; i < SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL; i++)
    {
        cfg.ant[i].row  = (int8_t) atoi(argv[argInd++]);
        cfg.ant[i].col  = (int8_t) atoi(argv[argInd++]);
    }

    /* Check if antenna spacings in X-dimesnsion is present  */
    if (argc > (1 + SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL*2))
    {
        cfg.antDistanceXdim = atof(argv[1 + SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL*2 + 0]) * 1e-3; //Saved in meters
    }
    /* Check if antenna spacings in Z-dimension is present  */
    if (argc > (1 + SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL*2 + 1))
    {
        cfg.antDistanceZdim = atof(argv[1 + SYS_COMMON_NUM_TX_ANTENNAS*SYS_COMMON_NUM_RX_CHANNEL*2 + 1]) * 1e-3; //Saved in meters
    }

    /* Save Configuration to use later */
    memcpy((void *) &gMmwMssMCB.antennaGeometryCfg, &cfg, sizeof(cfg));

    return 0;
}

static int32_t CLI_MMWaveSensorPositionCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 6)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    gMmwMssMCB.sceneryParams.sensorPosition.x           = (float) atof (argv[1]);
    gMmwMssMCB.sceneryParams.sensorPosition.y           = (float) atof (argv[2]);
    gMmwMssMCB.sceneryParams.sensorPosition.z           = (float) atof (argv[3]);
    
    gMmwMssMCB.sceneryParams.sensorOrientation.azimTilt      = (float) atof (argv[4]);
    gMmwMssMCB.sceneryParams.sensorOrientation.elevTilt    = (float) atof (argv[5]);

    return 0;
}

static int32_t CLI_MMWaveMpdBoundaryBox (int32_t argc, char* argv[])
{
    uint8_t i = 0;
    
    /* Sanity Check: Minimum argument check */
    if (argc != 8)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate configuration: */
    gMmwMssMCB.sceneryParams.numBoundaryBoxes++;
    
    i = gMmwMssMCB.sceneryParams.numBoundaryBoxes - 1;

    gMmwMssMCB.sceneryParams.boundaryBox[i].x1 = (float) atof (argv[2]);
    gMmwMssMCB.sceneryParams.boundaryBox[i].x2 = (float) atof (argv[3]);
    gMmwMssMCB.sceneryParams.boundaryBox[i].y1 = (float) atof (argv[4]);
    gMmwMssMCB.sceneryParams.boundaryBox[i].y2 = (float) atof (argv[5]);
    gMmwMssMCB.sceneryParams.boundaryBox[i].z1 = (float) atof (argv[6]);
    gMmwMssMCB.sceneryParams.boundaryBox[i].z2 = (float) atof (argv[7]);

    return 0;
}

static int32_t CLI_MMWaveClusterParamCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 4)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    gMmwMssMCB.clusterParamCfg.enabled = atoi (argv[1]);
    gMmwMssMCB.clusterParamCfg.maxDistance = atof (argv[2]);
    gMmwMssMCB.clusterParamCfg.minPoints = atoi (argv[3]);

    return 0;
}

static int32_t CLI_MMWaveMajorMotionStateCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 9)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    gMmwMssMCB.majorStateParamCfg.pointThre1 = atoi (argv[1]);
    gMmwMssMCB.majorStateParamCfg.pointThre2 = atoi (argv[2]);
    gMmwMssMCB.majorStateParamCfg.snrThre2 = atof (argv[3]);
    gMmwMssMCB.majorStateParamCfg.pointHistThre1 = atoi (argv[4]);
    gMmwMssMCB.majorStateParamCfg.pointHistThre2 = atoi (argv[5]);
    gMmwMssMCB.majorStateParamCfg.snrHistThre2 = atof (argv[6]);
    gMmwMssMCB.majorStateParamCfg.histBufferSize = atoi (argv[7]);
    gMmwMssMCB.majorStateParamCfg.stateExitThre = atoi (argv[8]);

    gMmwMssMCB.isMotionPresenceDpuEnabled = 1;
    return 0;
}

static int32_t CLI_MMWaveMinorMotionStateCfg (int32_t argc, char* argv[])
{
    /* Sanity Check: Minimum argument check */
    if (argc != 9)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    gMmwMssMCB.minorStateParamCfg.pointThre1 = atoi (argv[1]);
    gMmwMssMCB.minorStateParamCfg.pointThre2 = atoi (argv[2]);
    gMmwMssMCB.minorStateParamCfg.snrThre2 = atof (argv[3]);
    gMmwMssMCB.minorStateParamCfg.pointHistThre1 = atoi (argv[4]);
    gMmwMssMCB.minorStateParamCfg.pointHistThre2 = atoi (argv[5]);
    gMmwMssMCB.minorStateParamCfg.snrHistThre2 = atof (argv[6]);
    gMmwMssMCB.minorStateParamCfg.histBufferSize = atoi (argv[7]);
    gMmwMssMCB.minorStateParamCfg.stateExitThre = atoi (argv[8]);

    gMmwMssMCB.isMotionPresenceDpuEnabled = 1;
    return 0;
}

int32_t CLI_MMWaveSensorStart (int32_t argc, char* argv[])
{
    int32_t retVal = SystemP_SUCCESS;

    /* Sanity Check: Minimum argument check */
    if (argc != 5)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate the SensorStop configuration: */
    gMmwMssMCB.sensorStart.frameTrigMode      = atoi (argv[1]);
    gMmwMssMCB.sensorStart.chirpStartSigLbEn  = atoi (argv[2]); /* TODO: Remove */
    gMmwMssMCB.sensorStart.frameLivMonEn      = atoi (argv[3]);
    gMmwMssMCB.sensorStart.frameTrigTimerVal  = atoi (argv[4]);

    /* Calculate CRD NSLOPE Magnitude */
    {
        float scale, rfBandwidth, rampDownTime;
#ifdef SOC_XWRL64XX
        scale = 65536./(3*100*100);
#else
        scale = 65536./(4*100*100);
#endif
        rfBandwidth = (gMmwMssMCB.profileComCfg.h_ChirpRampEndTime*0.1) * gMmwMssMCB.chirpSlope; //In MHz/usec
        rampDownTime = MIN((gMmwMssMCB.profileTimeCfg.h_ChirpIdleTime*0.1-1.0), 6.0); //In usec
        gMmwMssMCB.profileComCfg.h_CrdNSlopeMag = (uint16_t) fabs((scale * rfBandwidth / rampDownTime + 0.5));
    }

    /* Chirp Timing Configuration */
    {
        gMmwMssMCB.profileTimeCfg.h_ChirpTxEnSel       = gMmwMssMCB.channelCfg.h_TxChCtrlBitMask;
        gMmwMssMCB.profileTimeCfg.h_ChirpTxBpmEnSel    = 0U;
    }
    /* FEC Power Config */
    {
        /* RDIF clock enable control.*/
        gMmwMssMCB.channelCfg.c_MiscCtrl = 1U << M_RL_RF_MISC_CTRL_RDIF_CLK;
    }

    /* FECSS RF Power ON*/
    retVal = rl_fecssRfPwrOnOff(M_DFP_DEVICE_INDEX_0, &gMmwMssMCB.channelCfg);
    if(retVal != M_DFP_RET_CODE_OK)
    {
        CLI_write ("Error: FECSS RF Power ON/OFF failed\r\n");
        retVal = SystemP_FAILURE;
    }

    /* Perform factory Calibrations. */
    retVal = mmwDemo_factoryCal();
    if(retVal != SystemP_SUCCESS)
    {
        CLI_write ("Error: mmWave factory calibration failed\r\n");
        retVal = SystemP_FAILURE;
    }
    isSensorStarted = 1;

    CLI_MMWStart();

    return retVal;
}

int32_t CLI_MMWStart(void)
{
    int32_t errCode = 0;
    demoStartTime = PRCMSlowClkCtrGet();

    #ifdef INA228
    I2C_Handle  i2cHandle = gI2cHandle[CONFIG_I2C0];
    #endif

    if(gMmwMssMCB.adcDataSourceCfg.source == 0)
    {
        //CLI_getMMWaveExtensionOpenConfig (&gMmwMssMCB.mmwOpenCfg);
        Mmwave_populateDefaultOpenCfg (&gMmwMssMCB.mmwOpenCfg);
        errCode = MmwDemo_openSensor();
        if(errCode != 0)
        {
            goto exit;
        }
        //CLI_getMMWaveExtensionConfig (&gMmwMssMCB.mmwCtrlCfg);
        Mmwave_populateDefaultChirpControlCfg (&gMmwMssMCB.mmwCtrlCfg); /* regular frame config */
        errCode = MmwDemo_configSensor();
        if(errCode != 0)
        {
            goto exit;
        }
    }

    gDpcTask = xTaskCreateStatic(mmwDemo_dpcTask, /* Pointer to the function that implements the task. */
                                 "dpc_task",      /* Text name for the task.  This is to facilitate debugging only. */
                                 DPC_TASK_STACK_SIZE,   /* Stack depth in units of StackType_t typically uint32_t on 32b CPUs */
                                 NULL,                  /* We are not using the task parameter. */
                                 DPC_TASK_PRI,          /* task priority, 0 is lowest priority, configMAX_PRIORITIES-1 is highest */
                                 gDpcTaskStack,      /* pointer to stack base */
                                 &gDpcTaskObj);         /* pointer to statically allocated task object memory */
    configASSERT(gDpcTask != NULL);


    gTlvTask = xTaskCreateStatic(mmwDemo_TransmitProcessedOutputTask, /* Pointer to the function that implements the task. */
                                 "tlv_task",      /* Text name for the task.  This is to facilitate debugging only. */
                                 TLV_TASK_STACK_SIZE,   /* Stack depth in units of StackType_t typically uint32_t on 32b CPUs */
                                 NULL,                  /* We are not using the task parameter. */
                                 TLV_TASK_PRI,          /* task priority, 0 is lowest priority, configMAX_PRIORITIES-1 is highest */
                                 gTlvTaskStack,      /* pointer to stack base */
                                 &gTlvTaskObj);         /* pointer to statically allocated task object memory */
    configASSERT(gTlvTask != NULL);

    if(gMmwMssMCB.adcDataSourceCfg.source == 0)
    {
        if (!gMmwMssMCB.oneTimeConfigDone)
        {
            /* Config INA sensors. */
            #ifdef INA228
            SensorConfig(i2cHandle);
            #endif
        }
        errCode = MmwDemo_startSensor();
        if(errCode != 0)
        {
            goto exit;
        }
    }
    else
    {
        if (!gMmwMssMCB.oneTimeConfigDone)
        {
            gAdcFileTask = xTaskCreateStatic(mmwDemo_adcFileReadTask, /* Pointer to the function that implements the task. */
                                     "adcFileRead_task",      /* Text name for the task.  This is to facilitate debugging only. */
                                     ADC_FILEREAD_TASK_STACK_SIZE,   /* Stack depth in units of StackType_t typically uint32_t on 32b CPUs */
                                     NULL,                  /* We are not using the task parameter. */
                                     ADC_FILEREAD_TASK_PRI,          /* task priority, 0 is lowest priority, configMAX_PRIORITIES-1 is highest */
                                     gAdcFileTaskStack,      /* pointer to stack base */
                                     &gAdcFileTaskObj);         /* pointer to statically allocated task object memory */
            configASSERT(gAdcFileTask != NULL);
        }
    }

    if (!gMmwMssMCB.oneTimeConfigDone)
    {
        gMmwMssMCB.oneTimeConfigDone = 1;
    }

exit:
    return errCode;
}

#ifdef ENABLE_UART_HIGH_BAUD_RATE_DYNAMIC_CFG
#include <drivers/uart.h>
#include "ti_drivers_config.h"
#include "ti_drivers_open_close.h"
extern UART_Params gUartParams[1];
void Drivers_uartInit();

static int32_t MmwDemo_CLIChangeUartBaudRate (int32_t argc, char* argv[])
{
    uint32_t baudRate;
    /* Sanity Check: Minimum argument check */
    if (argc != 2)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    baudRate = (uint32_t) atoi (argv[1]);

    gUartParams[0].baudRate = baudRate;

    Drivers_uartClose();
    UART_deinit();
    Drivers_uartInit();
    Drivers_uartOpen();

    return 0;
}
#endif

static int32_t CLI_MMWaveChannelCfg (int32_t argc, char* argv[])
{
    uint32_t i;
    /* Sanity Check: Minimum argument check */
    if (argc != 4)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Populate the frame configuration: */
    gMmwMssMCB.channelCfg.h_RxChCtrlBitMask  = atoi (argv[1]);
    gMmwMssMCB.channelCfg.h_TxChCtrlBitMask  = atoi (argv[2]);
    gMmwMssMCB.channelCfg.c_MiscCtrl         = atoi (argv[3]);


    gMmwMssMCB.numRxAntennas = 0;
    gMmwMssMCB.numTxAntennas = 0;
    for (i=0; i<16; i++)
    {
        if((gMmwMssMCB.channelCfg.h_TxChCtrlBitMask >> i) & 0x1)
        {
            gMmwMssMCB.numTxAntennas++;
        }
        if((gMmwMssMCB.channelCfg.h_RxChCtrlBitMask >> i) & 0x1)
        {
            gMmwMssMCB.rxAntOrder[gMmwMssMCB.numRxAntennas] = (uint8_t) i;
            gMmwMssMCB.numRxAntennas++;
        }
    }

#if 0
    //Currently we support ony 2Tx-3Rx
    if(gMmwMssMCB.numTxAntennas != 2)
    {
        CLI_write ("Error: Number of selected Tx antennas must be 2\n");
        return -1;
    }
    if(gMmwMssMCB.numRxAntennas != 3)
    {
        CLI_write ("Error: Number of selected Rx antennas must be 3\n");
        return -1;
    }
#endif

    return 0;
}

static int32_t CLI_MMWaveFactoryCalConfig (int32_t argc, char* argv[])
{
    if (argc != 6)
    {
        CLI_write ("Error: Invalid usage of the CLI command\r\n");
        return -1;
    }

    /* Validate inputs */
    /* <Save> and <re-store> shouldn't be enabled in CLI*/
    if ( ((uint32_t) atoi(argv[1]) == 1) && ((uint32_t) atoi(argv[2] ) == 1))
    {
        CLI_write ("Error: Save and Restore can be enabled only one at a time\r\n");
        return -1;
    }

    /* Validate inputs */
    /* RxGain should be between 30db to 40db */
    if ( ((uint32_t) atoi(argv[3]) > 40U) || ((uint32_t) atoi(argv[3] ) < 30U))
    {
        CLI_write ("Error: Valid RxGain should be between 30db to 40db\r\n");
        return -1;
    }

    /* txBackoffSel should be between 0db to 26db */
    if ((uint32_t) atoi(argv[4]) > 26U)
    {
        CLI_write ("Error: Valid txBackoffSel should be between 0db to 26db\r\n");
        return -1;
    }

    /* Populate configuration: */
    gMmwMssMCB.factoryCalCfg.saveEnable = (uint32_t) atoi(argv[1]);
    gMmwMssMCB.factoryCalCfg.restoreEnable = (uint32_t) atoi(argv[2]);
    gMmwMssMCB.factoryCalCfg.rxGain = (uint32_t) atoi(argv[3]);
    gMmwMssMCB.factoryCalCfg.txBackoffSel = (uint32_t)(2 * atoi(argv[4]));
    sscanf(argv[5], "0x%x", &gMmwMssMCB.factoryCalCfg.flashOffset);

    /* This check if to avoid accedently courrupt OOB Demo image. */
    if(gMmwMssMCB.factoryCalCfg.flashOffset < MMWDEMO_CALIB_FLASH_ADDR_1MB)
    {
        CLI_write ("Error: Valid flashOffset should be greater than 0x100000\r\n");
        DebugP_assert(0);
    }

    return 0;
}

static int32_t CLI_MMWaveMPDBoundaryBoxConfig (int32_t argc, char* argv[])
{
#if 0
    if (argc != 7)
    {
        CLI_write ("Error: Invalid usage of the CLI command\r\n");
        return -1;
    }
#endif
    return 0;
}

/**
 *  @b Description
 *  @n
 *      This is the CLI Handler for micro doppler processing configuration
 *
 *  @param[in] argc
 *      Number of arguments
 *  @param[in] argv
 *      Arguments
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */
static int32_t MmwDemo_CLIMicroDopplerParamCfg (int32_t argc, char* argv[])
{

    DPU_uDopProcCliCfg   cfg;
    int32_t             expectedArgc = 1+9;

    if (argc != expectedArgc)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Initialize configuration: */
    memset ((void *)&cfg, 0, sizeof(cfg));

    /* Populate configuration: */
    //"<enabled> <genApproach> <targetSize> <magnitudeSquared> <circShiftCentroid> <normalizedSpectrum> <interceptThrLowFreq> <interceptThrUpFreq> <specShiftMode>"
    cfg.enabled                 = (uint8_t) atoi (argv[1]);
    cfg.genApproach             = (uint8_t) atoi (argv[2]);
    cfg.targetSize              = (float)   atof (argv[3]);
    cfg.magnitudeSquared        = (uint8_t) atoi (argv[4]);
    cfg.circShiftAroundCentroid = (uint8_t) atoi (argv[5]);
    cfg.normalizedSpectrum      = (uint8_t) atoi (argv[6]);
    cfg.interceptThrLowFreq     = (float)   atof (argv[7]);
    cfg.interceptThrUpFreq      = (float)   atof (argv[8]);
    cfg.specShiftMode           = (uint8_t) atoi (argv[9]);

    /* Save Configuration to use later */
    memcpy(&gMmwMssMCB.microDopplerCliCfg, &cfg, sizeof(cfg));

    return 0;
}

/**
 *  @b Description
 *  @n
 *      This is the CLI Handler for measurement configuration of range bias
 *      and channel phase offsets
 *
 *  @param[in] argc
 *      Number of arguments
 *  @param[in] argv
 *      Arguments
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */
static int32_t MmwDemo_CLIMeasureRangeBiasAndRxChanPhaseCfg (int32_t argc, char* argv[])
{
    DPC_ObjectDetection_MeasureRxChannelBiasCliCfg   cfg;

    /* Sanity Check: Minimum argument check */
    if (argc != 4)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Initialize configuration: */
    memset ((void *)&cfg, 0, sizeof(cfg));

    /* Populate configuration: */
    cfg.enabled          = (uint8_t) atoi (argv[1]);
    cfg.targetDistance   = (float) atof (argv[2]);
    cfg.searchWinSize   = (float) atof (argv[3]);

    /* Save Configuration to use later */
    memcpy((void *) &gMmwMssMCB.measureRxChannelBiasCliCfg,
           &cfg, sizeof(cfg));

    return 0;
}

/**
 *  @b Description
 *  @n
 *      This is the CLI Handler for human/nonhuman classifier configuration
 *
 *  @param[in] argc
 *      Number of arguments
 *  @param[in] argv
 *      Arguments
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */
static int32_t MmwDemo_CLIClassifierParamCfg (int32_t argc, char* argv[])
{

    DPU_uDopClassifierCliCfg   cfg;
    int32_t             expectedArgc = 1+3;

    if (argc != expectedArgc)
    {
        CLI_write ("Error: Invalid usage of the CLI command\n");
        return -1;
    }

    /* Initialize configuration: */
    memset ((void *)&cfg, 0, sizeof(cfg));

    /* Populate configuration: */
    //"<enabled> "
    cfg.enabled                 = (uint8_t) atoi (argv[1]);
    cfg.minNumPntsPerTrack      = (uint8_t) atoi (argv[2]);
    cfg.missTotFrmThre          = (uint8_t) atoi (argv[3]);

    /* Save Configuration to use later */
    memcpy(&gMmwMssMCB.microDopplerClassifierCliCfg, &cfg, sizeof(cfg));

    return 0;
}
void CLI_write (const char* format, ...)
{
    va_list     arg;
    char        logMessage[256];
    int32_t     sizeMessage;
    UART_Transaction trans;

    UART_Transaction_init(&trans);

    /* Format the message: */
    va_start (arg, format);
    sizeMessage = vsnprintf (&logMessage[0], sizeof(logMessage), format, arg);
    va_end (arg);

    /* If CLI_write is called before CLI init has happened, return */
    if (gCLI.cfg.UartHandle == NULL)
    {
        return;
    }

    trans.buf   = &logMessage[0U];
    trans.count = sizeMessage;

    /* Log the message on the UART CLI console: */
    /* Blocking Mode: */
    UART_write (gCLI.cfg.UartHandle, &trans);
}

int32_t CLI_readLine(UART_Handle uartHandle, char *lineBuf, uint32_t bufSize)
{
    int32_t status = SystemP_FAILURE;

    if(uartHandle!=NULL)
    {
        uint32_t done = 0;
        UART_Transaction trans;
        uint8_t  readByte;
        int32_t  transferOK;
        uint32_t numCharRead = 0;

        while(!done)
        {
            UART_Transaction_init(&trans);

            status = SystemP_SUCCESS;

            /* Read one char */
            trans.buf   = &readByte;
            trans.count = 1;
            transferOK = UART_read(uartHandle, &trans);
            if((SystemP_SUCCESS != (transferOK)) || (UART_TRANSFER_STATUS_SUCCESS != trans.status))
            {
                status = SystemP_FAILURE;
            }
            if(status == SystemP_SUCCESS)
            {
                if(numCharRead < bufSize)
                {
                    lineBuf[numCharRead] = readByte;
                    numCharRead++;
                }

                /* Echo the char */
                trans.buf   = &readByte;
                trans.count = 1;
                transferOK = UART_write(uartHandle, &trans);
                if((SystemP_SUCCESS != (transferOK)) || (UART_TRANSFER_STATUS_SUCCESS != trans.status))
                {
                    status = SystemP_FAILURE;
                }
            }
            if(status == SystemP_SUCCESS)
            {
                if((readByte == 10) || (readByte == 13))/* "LINE FEED" "New Line" entered, (ASCII: 10, 13) */
                {
                    /* terminate the string, reset numCharRead  */
                    lineBuf[numCharRead-1] = 0;

                    done = 1;

                    /* Echo a new line to terminal (ASCII: 10) */
                    readByte = 10;
                    trans.buf   = &readByte;
                    trans.count = 1;
                    transferOK = UART_write(uartHandle, &trans);
                    if((SystemP_SUCCESS != (transferOK)) || (UART_TRANSFER_STATUS_SUCCESS != trans.status))
                    {
                        status = SystemP_FAILURE;
                    }
                }
            }
            if(status != SystemP_SUCCESS)
            {
                done = 1; /* break out in case of error */
            }
        }
    }
    return status;
}

void CLI_init (uint8_t taskPriority)
{

    CLI_Cfg     cliCfg;
    char        demoBanner[256];
    uint32_t    cnt;
    ATE_CalibData *ateCalib = (ATE_CalibData *)&gATECalibDataStorage;

    /* Create Demo Banner to be printed out by CLI */
    sprintf(&demoBanner[0],
                       "******************************************\r\n" \
                       "%s MMW Demo %02d.%02d.%02d.%02d\r\n"  \
                       "******************************************\r\n",
                        DEVICE_STRING,
                        MMWAVE_SDK_VERSION_MAJOR,
                        MMWAVE_SDK_VERSION_MINOR,
                        MMWAVE_SDK_VERSION_BUGFIX,
                        MMWAVE_SDK_VERSION_BUILD
            );

    /* Initialize the CLI configuration: */
    memset ((void *)&cliCfg, 0, sizeof(CLI_Cfg));

    /* Populate the CLI configuration: */
    cliCfg.cliPrompt                    = "mmwDemo:/>";
    cliCfg.cliBanner                    = demoBanner;
    cliCfg.UartHandle                   = gMmwMssMCB.commandUartHandle; // ToDo
    cliCfg.taskPriority                 = CLI_TASK_PRIORITY;
    cliCfg.mmWaveHandle                 = gMmwMssMCB.ctrlHandle; // ToDo
    cliCfg.enableMMWaveExtension        = 1U;
    cliCfg.usePolledMode                = true;
    cliCfg.overridePlatform             = false;
    cliCfg.overridePlatformString       = NULL;

    if(ateCalib->validityFlag != ATE_CALIB_DATA_VALID )
    {
        cliCfg.cliPrompt                = "mmwDemo:/> No valid ATE calibration available!\r\nPlease load and rerun ATE Calirbation application!";
    }

    cnt=0;
    cliCfg.tableEntry[cnt].cmd            = "sensorStop";
    cliCfg.tableEntry[cnt].helpString     = "<FrameStopMode>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveSensorStop;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "channelCfg";
    cliCfg.tableEntry[cnt].helpString     = "<RxChCtrlBitMask> <TxChCtrlBitMask> <MiscCtrl>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveChannelCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "chirpComnCfg";
    cliCfg.tableEntry[cnt].helpString     = "<DigOutputSampRate_Decim> <DigOutputBitsSel> <DfeFirSel> <NumOfAdcSamples> <ChirpTxMimoPatSel> <ChirpRampEndTime> <ChirpRxHpfSel>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveChirpCommonCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "chirpTimingCfg";
    cliCfg.tableEntry[cnt].helpString     = "<ChirpIdleTime> <ChirpAdcSkipSamples> <ChirpTxStartTime> <ChirpRfFreqSlope> <ChirpRfFreqStart>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveChirpTimingCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "frameCfg";
    cliCfg.tableEntry[cnt].helpString     = "<NumOfChirpsInBurst> <NumOfChirpsAccum> <BurstPeriodicity> <NumOfBurstsInFrame> <FramePeriodicity> <NumOfFrames>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveFrameCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "guiMonitor";
    cliCfg.tableEntry[cnt].helpString     = "<pointCloud> <rangeProfile> <noiseProfile> <rangeAzimuthHeatMap> <rangeDopplerHeatMap> <statsInfo> <presenceInfo> <adcSamples> <trackerInfo> <microDopplerInfo>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveGuiMonSel;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "sigProcChainCfg";
    cliCfg.tableEntry[cnt].helpString     = "<azimuthFftSize> <elevationFftSize> <motDetMode> <coherentDoppler> <numFrmPerMinorMotProc> <numMinorMotionChirpsPerFrame> <forceMinorMotionVelocityToZero> <minorMotionVelocityInclusionThr>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveSigProcChainCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "cfarCfg";
    cliCfg.tableEntry[cnt].helpString     = "<procDirection> <averageMode> <winLen> <guardLen> <noiseDiv> <cyclicMode> <thresholdScale> <peakGroupingEn>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveCfarCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "aoaFovCfg";
    cliCfg.tableEntry[cnt].helpString     = "<minAzimuthDeg> <maxAzimuthDeg> <minElevationDeg> <maxElevationDeg>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveAoaCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "rangeSelCfg";
    cliCfg.tableEntry[cnt].helpString     = "<minMeters> <maxMeters>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveRangeSelCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "clutterRemoval";
    cliCfg.tableEntry[cnt].helpString     = "<0-disable, 1-enable>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveClutterRemoval;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "compRangeBiasAndRxChanPhase";
    cliCfg.tableEntry[cnt].helpString     = "<rangeBias> <Re00> <Im00> <Re01> <Im01> <Re02> <Im02> <Re03> <Im03> <Re04> <Im04> <Re05> <Im05> ";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveCompRangeBiasAndRxChanPhaseCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "adcDataSource";
    cliCfg.tableEntry[cnt].helpString     = "<0-DFP, 1-File> <fileName>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveAdcDataSourceCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "adcLogging";
    cliCfg.tableEntry[cnt].helpString     = "<0-disable, 1-enable>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveAdcLogging;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "sensorPosition";
    cliCfg.tableEntry[cnt].helpString     = "<xOffset> <yOffset> <zOffset> <azimuthTilt> <elevationTilt>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveSensorPositionCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "mpdBoundaryBox";
    cliCfg.tableEntry[cnt].helpString     = "<zone_number> <xMin> <xMax> <yMin> <yMax> <zMin> <zMax>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveMpdBoundaryBox;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "clusterCfg";
    cliCfg.tableEntry[cnt].helpString     = "<0-disable, 1-enable> <cluster_radius> <minPoints>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveClusterParamCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "majorStateCfg";
    cliCfg.tableEntry[cnt].helpString     = "<pointThre1> <pointThre2> <snrThre2> <pointHistThre1> <pointHistThre2> <snrHistThre2> <histBuffSize> <stateExitThre>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveMajorMotionStateCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "minorStateCfg";
    cliCfg.tableEntry[cnt].helpString     = "<pointThre1> <pointThre2> <snrThre2> <pointHistThre1> <pointHistThre2> <snrHistThre2> <histBuffSize> <stateExitThre>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveMinorMotionStateCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "sensorStart";
    cliCfg.tableEntry[cnt].helpString     = "<FrameTrigMode> <LoopBackEn> <FrameLivMonEn> <FrameTrigTimerVal>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveSensorStart;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "lowPowerCfg";
    cliCfg.tableEntry[cnt].helpString     = "<LowPowerModeEnable>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveLowPwrModeEnable;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "factoryCalibCfg";
    cliCfg.tableEntry[cnt].helpString     = "<save enable> <restore enable> <rxGain> <backoff0> <Flash offset>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = CLI_MMWaveFactoryCalConfig;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "trackingCfg";
    cliCfg.tableEntry[cnt].helpString     = "<enable> <paramSet> <numPoints> <numTracks> <maxDoppler> <framePeriod>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLITrackingCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd             = "staticBoundaryBox";
    cliCfg.tableEntry[cnt].helpString      = "<X min> <X Max> <Y min> <Y max> <Z min> <Z max>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = MmwDemo_CLIStaticBoundaryBoxCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd             = "boundaryBox";
    cliCfg.tableEntry[cnt].helpString      = "<X min> <X Max> <Y min> <Y max> <Z min> <Z max>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = MmwDemo_CLIBoundaryBoxCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd             = "gatingParam";// PC: 4 gating volume, Limits are set to 3m in length, 2m in width, 0 no limit in doppler
    cliCfg.tableEntry[cnt].helpString      = "<gating volume> <length> <width> <doppler>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = MmwDemo_CLIGatingParamCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd             = "stateParam";// PC: 10 frames to activate, 5 to forget, 10 active to free, 1000 static to free, 5 exit to free, 6000 sleep to free
    cliCfg.tableEntry[cnt].helpString      = "<det2act> <det2free> <act2free> <stat2free> <exit2free> <sleep2free>";//det2act, det2free, act2free, stat2free, exit2free, sleep2free
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = MmwDemo_CLIStateParamCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd             = "allocationParam";// PC: 250 SNR, 0.1 minimal velocity, 5 points, 1m in distance, 2m/s in velocity
    cliCfg.tableEntry[cnt].helpString      = "<SNRs> <minimal velocity> <points> <in distance> <in velocity>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = MmwDemo_CLIAllocationParamCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd             = "maxAcceleration";
    cliCfg.tableEntry[cnt].helpString      = "<max X acc.> <max Y acc.> <max Z acc.>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = MmwDemoCLIMaxAccelerationParamCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd             = "presenceBoundaryBox";
    cliCfg.tableEntry[cnt].helpString      = "<X min> <X Max> <Y min> <Y max> <Z min> <Z max>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = MmwDemo_CLIPresenceParamCfg;
    cnt++;

#ifdef ENABLE_UART_HIGH_BAUD_RATE_DYNAMIC_CFG
    cliCfg.tableEntry[cnt].cmd             = "baudRate";
    cliCfg.tableEntry[cnt].helpString      = "<baudRate>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = MmwDemo_CLIChangeUartBaudRate;
    cnt++;
#endif

    cliCfg.tableEntry[cnt].cmd             = "antGeometryCfg";
    cliCfg.tableEntry[cnt].helpString      = "<row0> <col0> <row1> <col1> <row2> <col2> <row3> <col3> <row4> <col4> <row5> <col5> <antDistX (mm)> <antDistY (mm)>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = CLI_MmwDemo_AntGeometryCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd             = "microDopplerCfg";
    cliCfg.tableEntry[cnt].helpString      = "<enabled> <genApproach> <targetSize> <magnitudeSquared> <circShiftCentroid> <normalizedSpectrum> <interceptThrLowFreq> <interceptThrUpFreq> <specShiftMode>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = MmwDemo_CLIMicroDopplerParamCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd             = "classifierCfg";
    cliCfg.tableEntry[cnt].helpString      = "<enabled> <minNumPntsPerTrack> <missTotFrmThre>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn   = MmwDemo_CLIClassifierParamCfg;
    cnt++;

    cliCfg.tableEntry[cnt].cmd            = "measureRangeBiasAndRxChanPhase";
    cliCfg.tableEntry[cnt].helpString     = "<enabled> <targetDistance> <searchWin>";
    cliCfg.tableEntry[cnt].cmdHandlerFxn  = MmwDemo_CLIMeasureRangeBiasAndRxChanPhaseCfg;
    cnt++;

    cnt++;

    /* Open the CLI: */
    if (CLI_open (&cliCfg) < 0)
    {
        DebugP_log ("Error: Unable to open the CLI\r\n");
        return;
    }
}

int32_t CLI_open (CLI_Cfg* ptrCLICfg)
{
    uint32_t        index;

    /* Sanity Check: Validate the arguments */
    if (ptrCLICfg == NULL)
        return -1;

    /* Initialize the CLI MCB: */
    memset ((void*)&gCLI, 0, sizeof(CLI_MCB));

    /* Copy over the configuration: */
    memcpy ((void *)&gCLI.cfg, (void *)ptrCLICfg, sizeof(CLI_Cfg));

    /* Cycle through and determine the number of supported CLI commands: */
    for (index = 0; index < CLI_MAX_CMD; index++)
    {
        /* Do we have a valid entry? */
        if (gCLI.cfg.tableEntry[index].cmd == NULL)
        {
            /* NO: This is the last entry */
            break;
        }
        else
        {
            /* YES: Increment the number of CLI commands */
            gCLI.numCLICommands = gCLI.numCLICommands + 1;
        }
    }

    /* Do we have a CLI Prompt specified?  */
    if (gCLI.cfg.cliPrompt == NULL)
        gCLI.cfg.cliPrompt = "CLI:/>";

    /* The CLI provides a help command by default:
     * - Since we are adding this at the end of the table; a user of this module can also
     *   override this to provide its own implementation. */
    gCLI.cfg.tableEntry[gCLI.numCLICommands].cmd           = "help";
    gCLI.cfg.tableEntry[gCLI.numCLICommands].helpString    = NULL;
    gCLI.cfg.tableEntry[gCLI.numCLICommands].cmdHandlerFxn = CLI_help;

    /* Increment the number of CLI commands: */
    gCLI.numCLICommands++;

    gCliTask = xTaskCreateStatic( CLI_task,   /* Pointer to the function that implements the task. */
                                  "cli_task_main", /* Text name for the task.  This is to facilitate debugging only. */
                                  CLI_TASK_STACK_SIZE,  /* Stack depth in units of StackType_t typically uint32_t on 32b CPUs */
                                  NULL,              /* We are not using the task parameter. */
                                  ptrCLICfg->taskPriority,      /* task priority, 0 is lowest priority, configMAX_PRIORITIES-1 is highest */
                                  gCliTskStack,  /* pointer to stack base */
                                  &gCliTaskObj );    /* pointer to statically allocated task object memory */
    configASSERT(gCliTask != NULL);

    return 0;
}
